home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / news / inn1.000 / inn1.4sec-linux-src.tar / inn / innd / icd.c < prev    next >
C/C++ Source or Header  |  1993-01-29  |  8KB  |  383 lines

  1. /*  $Revision: 1.26 $
  2. **
  3. **  Routines to read and write the active file.
  4. */
  5. #include "innd.h"
  6. #if    defined(ACT_MMAP)
  7. #include <sys/mman.h>
  8. #endif    /* defined(ACT_MMAP) */
  9. #include <sys/uio.h>
  10.  
  11. typedef struct iovec    IOVEC;
  12.  
  13.  
  14. STATIC char        ICDactpath[] = _PATH_ACTIVE;
  15. STATIC char        *ICDactpointer;
  16. STATIC int        ICDactfd;
  17. STATIC int        ICDactsize;
  18.  
  19.  
  20. /*
  21. **  Set and unset (or copy) IOVEC elements.  We make copies to
  22. **  avoid problems with mmap.
  23. */
  24. #if    defined(ACT_MMAP)
  25. #define ICDiovset(iovp, base, len)    \
  26.     do { \
  27.         (iovp)->iov_len = len; \
  28.         (iovp)->iov_base = NEW(char, (iovp)->iov_len); \
  29.         (void)memcpy((POINTER)(iovp)->iov_base, (POINTER)base, \
  30.             (SIZE_T)(iovp)->iov_len); \
  31.     } while (JUSTONCE)
  32. #define ICDiovrelease(iovp)        DISPOSE((iovp)->iov_base)
  33.  
  34. #if    defined(MAP_FILE)
  35. #define MAP__ARG    (MAP_FILE | MAP_SHARED)
  36. #else
  37. #define MAP__ARG    (MAP_SHARED)
  38. #endif    /* defined(MAP_FILE) */
  39.  
  40. #else
  41.  
  42. #define ICDiovset(iovp, base, len)    \
  43.     (iovp)->iov_base = base, (iovp)->iov_len = len
  44. #define ICDiovrelease(iovp)        /* NULL */
  45. #endif    /* defined(ACT_MMAP) */
  46.  
  47.  
  48. /*
  49. **  Close the active file, releasing its resources.
  50. */
  51. STATIC void
  52. ICDcloseactive()
  53. {
  54.     if (ICDactpointer) {
  55. #if    defined(ACT_MMAP)
  56.     if (munmap(ICDactpointer, ICDactsize) < 0)
  57.         syslog(L_ERROR, "%s cant munmap %m", LogName, ICDactpath);
  58. #else
  59.     DISPOSE(ICDactpointer);
  60. #endif    /* defined(ACT_MMAP) */
  61.     ICDactpointer = NULL;
  62.     if (close(ICDactfd) < 0) {
  63.         syslog(L_FATAL, "%s cant close %s %m", LogName, ICDactpath);
  64.         exit(1);
  65.     }
  66.     }
  67. }
  68.  
  69.  
  70. /*
  71. **  Set up the hash and in-core tables.
  72. */
  73. void
  74. ICDsetup(StartSites)
  75.     BOOL    StartSites;
  76. {
  77.     ICDneedsetup = FALSE;
  78.     ICDcloseactive();
  79.     NGparsefile();
  80.     if (NGfind("control") == NULL || NGfind("junk") == NULL) {
  81.     syslog(L_FATAL, "%s internal no control and/or junk group", LogName);
  82.     exit(1);
  83.     }
  84. #if    defined(DO_MERGE_TO_GROUPS)
  85.     if (NGfind("to") == NULL) {
  86.     syslog(L_FATAL, "%s internal no to group", LogName);
  87.     exit(1);
  88.     }
  89. #endif    /* defined(DO_MERGE_TO_GROUPS) */
  90.     SITEparsefile(StartSites);
  91. }
  92.  
  93.  
  94. /*
  95. **  Write out all in-core data.
  96. */
  97. void
  98. ICDwrite()
  99. {
  100.     HISsync();
  101.  
  102.     if (ICDactivedirty) {
  103.     ICDwriteactive();
  104.     ICDactivedirty = 0;
  105.     }
  106.  
  107.     /* Flush log and error log. */
  108.     if (fflush(Log) == EOF)
  109.     syslog(L_ERROR, "%s cant fflush log %m", LogName);
  110.     if (fflush(Errlog) == EOF)
  111.     syslog(L_ERROR, "%s cant fflush errlog %m", LogName);
  112. }
  113.  
  114.  
  115. /*
  116. **  Close things down.
  117. */
  118. void
  119. ICDclose()
  120. {
  121.     ICDwrite();
  122.     ICDcloseactive();
  123. }
  124.  
  125.  
  126. /*
  127. **  Scan the active file, and renumber the min/max counts.
  128. */
  129. void
  130. ICDrenumberactive()
  131. {
  132.     register int    i;
  133.     register NEWSGROUP    *ngp;
  134.  
  135.     for (i = nGroups, ngp = Groups; --i >= 0; ngp++)
  136.     if (!NGrenumber(ngp))
  137.         break;
  138.     if (i < 0)
  139.     ICDwrite();
  140. }
  141.  
  142.  
  143. /*
  144. **  Use writev() to replace the active file.
  145. */
  146. STATIC BOOL
  147. ICDwritevactive(vp, vpcount)
  148.     IOVEC        *vp;
  149.     int            vpcount;
  150. {
  151.     static char        BACKUP[] = _PATH_OLDACTIVE;
  152.     static char        WHEN[] = "backup active";
  153.     register int    fd;
  154.     char        *dummy;
  155.  
  156.     /* Write the current file to a backup. */
  157.     if (unlink(BACKUP) < 0 && errno != ENOENT) {
  158.     IOError(WHEN);
  159.     syslog(L_ERROR, "%s cant unlink %s %m", LogName, BACKUP);
  160.     }
  161.     if ((fd = open(BACKUP, O_WRONLY | O_TRUNC | O_CREAT, 0664)) < 0) {
  162.     IOError(WHEN);
  163.     syslog(L_ERROR, "%s cant open %s %m", LogName, BACKUP);
  164.     }
  165.     else if (xwrite(fd, ICDactpointer, ICDactsize) < 0) {
  166.     IOError(WHEN);
  167.     syslog(L_ERROR, "%s cant write %s %m", LogName, BACKUP);
  168.     (void)close(fd);
  169.     }
  170.     else if (close(fd) < 0) {
  171.     IOError(WHEN);
  172.     syslog(L_ERROR, "%s cant close %s %m", LogName, BACKUP);
  173.     }
  174.  
  175.     /* Open the active file. */
  176.     fd = open(ICDactpath, O_WRONLY | O_TRUNC | O_CREAT, ARTFILE_MODE);
  177.     if (fd < 0) {
  178.     IOError(WHEN);
  179.     syslog(L_ERROR, "%s cant open %s %m", LogName, ICDactpath);
  180.     return FALSE;
  181.     }
  182.  
  183.     /* Write it. */
  184.     if (xwritev(fd, vp, vpcount) < 0) {
  185.     IOError(WHEN);
  186.     syslog(L_ERROR, "%s cant write %s %m", LogName, ICDactpath);
  187.     (void)close(fd);
  188.     return FALSE;
  189.     }
  190.  
  191.     /* Close it. */
  192.     (void)close(fd);
  193.     if (AmRoot)
  194.     xchown(ICDactpath);
  195.  
  196.     /* Invalidate in-core pointers. */
  197.     ICDcloseactive();
  198.  
  199.     /* Restore in-core pointers. */
  200.     if (Mode != OMrunning) {
  201.     ICDneedsetup = TRUE;
  202.     /* Force the active file into memory. */
  203.     (void)ICDreadactive(&dummy);
  204.     }
  205.     else
  206.     ICDsetup(TRUE);
  207.     return TRUE;
  208. }
  209.  
  210.  
  211. /*
  212. **  Change the flag on a newsgroup.  Fairly easy.
  213. */
  214. BOOL
  215. ICDchangegroup(ngp, Rest)
  216.     NEWSGROUP        *ngp;
  217.     char        *Rest;
  218. {
  219.     static char        NEWLINE[] = "\n";
  220.     register int    i;
  221.     IOVEC        iov[3];
  222.     BOOL        ret;
  223.  
  224.     /* Set up the scatter/gather vectors. */
  225.     ICDiovset(&iov[0], ICDactpointer, ngp->Rest - ICDactpointer);
  226.     ICDiovset(&iov[1], Rest, strlen(Rest));
  227.     if (++ngp < &Groups[nGroups]) {
  228.     /* Not the last group, keep the \n from the next line. */
  229.     i = ngp->Start;
  230.     ICDiovset(&iov[2], &ICDactpointer[i - 1], ICDactsize - i + 1);
  231.     }
  232.     else {
  233.     /* Last group -- append a newline. */
  234.     ICDiovset(&iov[2], NEWLINE, STRLEN(NEWLINE));
  235.     }
  236.     ret = ICDwritevactive(iov, 3);
  237.     ICDiovrelease(&iov[0]);
  238.     ICDiovrelease(&iov[1]);
  239.     ICDiovrelease(&iov[2]);
  240.     return ret;
  241. }
  242.  
  243.  
  244. /*
  245. **  Add a newsgroup.  Append a line to the end of the active file and reload.
  246. */
  247. BOOL
  248. ICDnewgroup(Name, Rest)
  249.     char        *Name;
  250.     char        *Rest;
  251. {
  252.     char        buff[SMBUF];
  253.     IOVEC        iov[2];
  254.     BOOL        ret;
  255.  
  256.     /* Set up the scatter/gather vectors. */
  257.     if (strlen(Name) + strlen(Rest) > (SIZE_T)(SMBUF - 24)) {
  258.     syslog(L_ERROR, "%s too_long %s", LogName, MaxLength(Name, Name));
  259.     return FALSE;
  260.     }
  261.     (void)sprintf(buff, "%s 0000000000 0000000001 %s\n", Name, Rest);
  262.     ICDiovset(&iov[0], ICDactpointer, ICDactsize);
  263.     ICDiovset(&iov[1], buff, strlen(buff));
  264.  
  265.     ret = ICDwritevactive(iov, 2);
  266.     ICDiovrelease(&iov[0]);
  267.     ICDiovrelease(&iov[1]);
  268.     return ret;
  269. }
  270.  
  271.  
  272. /*
  273. **  Remove a newsgroup.  Splice the line out of the active file and reload.
  274. */
  275. BOOL
  276. ICDrmgroup(ngp)
  277.     NEWSGROUP    *ngp;
  278. {
  279.     IOVEC    iov[2];
  280.     int        i;
  281.     BOOL    ret;
  282.  
  283.     /* If this is the first group in the file, write everything after. */
  284.     if (ngp == &Groups[0]) {
  285.     i = ngp[1].Start;
  286.     ICDiovset(&iov[0], &ICDactpointer[i], ICDactsize - i);
  287.     ret = ICDwritevactive(iov, 1);
  288.     ICDiovrelease(&iov[0]);
  289.     return ret;
  290.     }
  291.  
  292.     /* Write everything up to this group. */
  293.     ICDiovset(&iov[0], ICDactpointer, ngp->Start);
  294.  
  295.     /* If this is the last group, that's all we have to write. */
  296.     if (ngp == &Groups[nGroups - 1]) {
  297.     ret = ICDwritevactive(iov, 1);
  298.     ICDiovrelease(&iov[0]);
  299.     return ret;
  300.     }
  301.  
  302.     /* Write everything after this group. */
  303.     i = ngp[1].Start;
  304.     ICDiovset(&iov[1], &ICDactpointer[i], ICDactsize - i);
  305.     ret = ICDwritevactive(iov, 2);
  306.     ICDiovrelease(&iov[0]);
  307.     ICDiovrelease(&iov[1]);
  308.     return ret;
  309. }
  310.  
  311.  
  312.  
  313. /*
  314. **  Open the active file and "map" it into memory.
  315. */
  316. char *
  317. ICDreadactive(endp)
  318.     char        **endp;
  319. {
  320.     struct stat        Sb;
  321.  
  322.     if (ICDactpointer) {
  323.     *endp = ICDactpointer + ICDactsize;
  324.     return ICDactpointer;
  325.     }
  326.  
  327.     if ((ICDactfd = open(ICDactpath, O_RDWR)) < 0) {
  328.     syslog(L_FATAL, "%s cant open %s %m", LogName, ICDactpath);
  329.     exit(1);
  330.     }
  331.     CloseOnExec(ICDactfd, TRUE);
  332.  
  333. #if    defined(ACT_MMAP)
  334.     if (fstat(ICDactfd, &Sb) < 0) {
  335.     syslog(L_FATAL, "%s cant fstat %d %s %m",
  336.         LogName, ICDactfd, ICDactpath);
  337.     exit(1);
  338.     }
  339.     ICDactsize = Sb.st_size;
  340.     ICDactpointer = mmap((caddr_t)0, ICDactsize, PROT_READ|PROT_WRITE,
  341.             MAP__ARG, ICDactfd, (off_t)0);
  342.     if (ICDactpointer == (char *)-1) {
  343.     syslog(L_FATAL, "%s cant mmap %d %s %m",
  344.         LogName, ICDactfd, ICDactpath);
  345.     exit(1);
  346.     }
  347.  
  348. #else
  349.  
  350.     if ((ICDactpointer = ReadInDescriptor(ICDactfd, &Sb)) == NULL) {
  351.     syslog(L_FATAL, "%s cant read %s %m", LogName, ICDactpath);
  352.     exit(1);
  353.     }
  354.     ICDactsize = Sb.st_size;
  355. #endif    /* defined(ACT_MMAP) */
  356.  
  357.     *endp = ICDactpointer + ICDactsize;
  358.     return ICDactpointer;
  359. }
  360.  
  361.  
  362. /*
  363. **  Write the active file out.
  364. */
  365. void
  366. ICDwriteactive()
  367. {
  368. #if    defined(ACT_MMAP)
  369.     /* No-op. */
  370.  
  371. #else
  372.  
  373.     if (lseek(ICDactfd, 0L, SEEK_SET) == -1) {
  374.     syslog(L_FATAL, "%s cant rewind %s %m", LogName, ICDactpath);
  375.     exit(1);
  376.     }
  377.     if (xwrite(ICDactfd, ICDactpointer, ICDactsize) < 0) {
  378.     syslog(L_FATAL, "%s cant write %s %m", LogName, ICDactpath);
  379.     exit(1);
  380.     }
  381. #endif    /* defined(ACT_MMAP) */
  382. }
  383.